﻿using System;
using System.Drawing;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;

namespace DarkAngels.WoW.Library.Network
{
    public class SimpleNetworking : DarkAngels.WoW.Library.Interfaces.INetworking
    {
        public SimpleNetworking()
        {
            UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.5.21022; .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0)";
        }
        #region INetworking Members
        public String GetFile(string uri)
        {
            this.Uri = uri;
            //open a connection with the connection manager
            _OpenConnection();
            //fetch the wanted file
            //create a request object
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(this.Uri);
            //set method to "GET"
            request.Method = "GET";
            //Setting the user agent to trick the armory into serving us the XML and not styled html
            request.UserAgent = UserAgent;

            // check if a proxy has been set
            if (Proxy != null)
                request.Proxy = Proxy;

            //store our response in a new stream
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            //store the stream to memory so we can close the connection
            String memory = "";
            StreamReader sr = new StreamReader(response.GetResponseStream());
            memory = sr.ReadToEnd();
            sr.Close();
            sr.Dispose();
            //close any open connections we have with the connection manager
            _CloseConnection();
            return memory;
        }
        public Image GetImage(string uri)
        {
            this.Uri = uri;
            _OpenConnection();
            System.Net.WebRequest request = System.Net.WebRequest.Create(this.Uri);
            System.Net.WebResponse response = request.GetResponse();
            System.IO.Stream responseStream = response.GetResponseStream();
            Bitmap bitmap2 = new Bitmap(responseStream);
            _CloseConnection();
            return bitmap2;
        }
        #endregion

        public String UserAgent
        {
            get;
            set;
        }

        internal String Uri
        {
            get;
            set;
        }

        public WebProxy Proxy
        {
            get;
            set;
        }

        //CommMan methods are based on the connection manager sample found at the msdn website
        //Link: http://msdn.microsoft.com/da-dk/netframework/dd296752(en-us).aspx
        #region CommMan methods
        IntPtr hConnection = IntPtr.Zero;

        public void _OpenConnection()
        {
            Guid networkGuid = Guid.Empty;
            ConnMgrStatus status = ConnMgrStatus.Unknown;
            ConnMgrMapURL(Uri, ref networkGuid, 0);
            ConnMgrConnectionInfo info = new ConnMgrConnectionInfo(networkGuid);
            ConnMgrEstablishConnectionSync(info, ref hConnection, 0, ref status);
        }

        public void _CloseConnection()
        {
            if (hConnection != IntPtr.Zero)
            {
                ConnMgrReleaseConnection(hConnection, 0);
                hConnection = IntPtr.Zero;
            }
        }

        #region Connection Manager Methods and Types

        [DllImport("CellCore.dll")]
        static extern int ConnMgrMapURL(string url, ref Guid networkGuid, int passZero);
        [DllImport("CellCore.dll")]
        static extern int ConnMgrEstablishConnection(ConnMgrConnectionInfo connectionInfo, ref IntPtr connectionHandle);
        [DllImport("CellCore.dll")]
        static extern int ConnMgrEstablishConnectionSync(ConnMgrConnectionInfo connectionInfo, ref IntPtr connectionHandle,
            uint dwTimeout, ref ConnMgrStatus dwStatus);
        [DllImport("CellCore.dll")]
        static extern int ConnMgrReleaseConnection(IntPtr connectionHandle, int cache);
        [DllImport("CellCore.dll")]
        static extern int ConnMgrConnectionStatus(IntPtr connectionHandle, ref ConnMgrStatus status);

        [StructLayout(LayoutKind.Sequential)]
        class ConnMgrConnectionInfo
        {
            public ConnMgrConnectionInfo()
            {
                cbSize = Marshal.SizeOf(typeof(ConnMgrConnectionInfo));
            }

            public ConnMgrConnectionInfo(Guid destination, ConnMgrPriority priority, ConnMgrProxy proxy)
                : this()
            {
                guidDestNet = destination;
                dwParams = ConnMgrParam.GuidDestNet;
                dwPriority = priority;
                dwFlags = proxy;
            }

            public ConnMgrConnectionInfo(Guid destination, ConnMgrPriority priority)
                : this(destination, priority, ConnMgrProxy.NoProxy) { }

            public ConnMgrConnectionInfo(Guid destination)
                : this(destination, ConnMgrPriority.UserInteractive) { }

            Int32 cbSize;                          // DWORD
            public ConnMgrParam dwParams = 0;      // DWORD
            public ConnMgrProxy dwFlags = 0;       // DWORD
            public ConnMgrPriority dwPriority = 0; // DWORD
            public Int32 bExclusive = 0;           // BOOL
            public Int32 bDisabled = 0;            // BOOL
            public Guid guidDestNet = Guid.Empty;  // GUID
            public IntPtr hWnd = IntPtr.Zero;      // HWND
            public UInt32 uMsg = 0;                // UINT
            public Int32 lParam = 0;               // LPARAM
            public UInt32 ulMaxCost = 0;           // ULONG
            public UInt32 ulMinRcvBw = 0;          // ULONG
            public UInt32 ulMaxConnLatency = 0;    // ULONG 
        } ;


        [Flags]
        enum ConnMgrParam : int
        {
            GuidDestNet = 0x1,
            MaxCost = 0x2,
            MinRcvBw = 0x4,
            MaxConnLatency = 0x8
        }

        [Flags]
        enum ConnMgrProxy : int
        {
            NoProxy = 0x0,
            Http = 0x1,
            Wap = 0x2,
            Socks4 = 0x4,
            Socks5 = 0x8
        }

        enum ConnMgrPriority
        {
            UserInteractive = 0x8000,
            HighPriorityBackground = 0x0200,
            LowPriorityBackground = 0x0008
        }

        enum ConnMgrStatus
        {
            Unknown = 0x00,
            Connected = 0x10,
            Suspended = 0x11,
            Disconnected = 0x20,
            ConnectionFailed = 0x21,
            ConnectionCanceled = 0x22,
            ConnectionDisabled = 0x23,
            NoPathToDestination = 0x24,
            WaitingForPath = 0x25,
            WaitingForPhone = 0x26,
            PhoneOff = 0x27,
            ExclusiveConflict = 0x28,
            NoResources = 0x29,
            ConnectionLinkFailed = 0x2a,
            AuthenticationFailed = 0x2b,
            NoPathWithProperty = 0x2c,
            WaitingConnection = 0x40,
            WaitingForResource = 0x41,
            WaitingForNetwork = 0x42,
            WaitingDisconnection = 0x80,
            WaitingConnectionAbort = 0x81
        }

        #endregion
        #endregion
    }
}
